import current from '../core/current';
import logger from '../core/logger';
import followMusician from '../model/music/followMusician';
import musicCategroies from '../model/music/musicCategroies';
import musicCateMenus from '../model/music/musicCateMenus';
import musicHome, { musicHomeMenu, musicHomeSong } from '../model/music/musicHome';
import musicianInfo from '../model/music/musicianInfo';
import musicMenu from '../model/music/musicMenu';
import musicSearchMenu from '../model/music/musicSearchMenu';
import musicSearchUser from '../model/music/musicSearchUser';
import songCollections from '../model/music/songCollections';
import songInfo from '../model/music/songInfo';
import returnModel from '../model/common/returnModel';
import apiInfo from './core/apiInfo';
import apiProvider from './core/apiProvider';
import { clientBase } from './core/clientBase';
import dataInfo from './core/dataInfo';

export class musicClient extends clientBase {
  constructor() {
    super();
  }

  getHome(): Promise<returnModel<musicHome>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        let info = new apiInfo("https://api.bilibili.com/audio/music-service-c/firstpage", '', null, false);
        this.client.getResult(info).then((res) => {
          if (res.code == 0) {
            var data: musicHome = res;
            resolve(self.buildSuccessResult<musicHome>(data));
          } else
            resolve(self.buildFailedResult<musicHome>(res.message));
        });
      } catch (e) {
        logger.error(e);
        resolve(super.buildExceptionResult<musicHome>(e));
      }
    });
  }

  getInfo(id: number): Promise<returnModel<any>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        let info = new apiInfo("https://api.bilibili.com/audio/music-service-c/url", `&mid=${current.instance.mid}&privilege=2&quality=1&songid=${id}`, null, true);
        this.client.getResult(info).then((res) => {
          if (res.code == 0)
            resolve(self.buildSuccessResult<any>(res));
          else
            resolve(self.buildFailedResult<any>(res.message));
        });
      } catch (e) {
        logger.error(e);
        resolve(super.buildExceptionResult<any>(e));
      }
    });
  }

  getDetail(menuId: string): Promise<returnModel<musicMenu>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        let info = new apiInfo(`https://api.bilibili.com/audio/music-service-c/menus/${menuId}`, `&mid=${current.instance.mid}`, null, false);
        this.client.getResult(info).then((res) => {
          if (res.code == 0) {
            var data: musicMenu = res;
            resolve(self.buildSuccessResult<musicMenu>(data));
          } else
            resolve(self.buildFailedResult<musicMenu>(res.message));
        });
      } catch (e) {
        logger.error(e);
        resolve(super.buildExceptionResult<musicMenu>(e));
      }
    });
  }

  getCateMenus(type: number, cateId: number, itemId: number, orderBy: number, pageNum: number): Promise<returnModel<musicCateMenus>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        let info;
        switch (type) {
          case 0: {
            info = new apiInfo("https://api.bilibili.com/audio/music-service-c/menus/filteMenu", `&cateId=${cateId}&itemId=${itemId}&orderBy=${orderBy}&pageNum=${pageNum}&pageSize=24`, null, true);
            break;
          }
          case 1: {
            info = new apiInfo("https://api.bilibili.com/audio/music-service-c/menus/filte-pmenu", `&cateId=${cateId}&itemId=${itemId}&orderBy=${orderBy}&pageNum=${pageNum}&pageSize=24`, null, true);
            break;
          }
          case 2: {
            info = new apiInfo("https://api.bilibili.com/audio/music-service-c/menus/missevan", `&cateId=${cateId}&itemId=${itemId}&orderBy=${orderBy}&pageNum=${pageNum}&pageSize=24`, null, true);
            break;
          }
        }
        this.client.getResult(info).then((res) => {
          if (res.code == 0) {
            var data: musicCateMenus = res;
            resolve(self.buildSuccessResult<musicCateMenus>(data));
          } else
            resolve(self.buildFailedResult<musicCateMenus>(res.message));
        });
      } catch (e) {
        logger.error(e);
        resolve(super.buildExceptionResult<musicCateMenus>(e));
      }
    });
  }

  getCategroies(type: number): Promise<returnModel<musicCategroies>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        let info;
        switch (type) {
          case 0: {
            info = new apiInfo("https://api.bilibili.com/audio/music-service-c/categroies/menucate", '', null, true);
            break;
          }
          case 1: {
            info = new apiInfo("https://api.bilibili.com/audio/music-service-c/categroies/pmenucate", '', null, true);
            break;
          }
          case 2: {
            info = new apiInfo("https://api.bilibili.com/audio/music-service-c/categroies/missevan", '', null, true);
            break;
          }
        }
        this.client.getResult(info).then((res) => {
          if (res.code == 0) {
            var data: musicCategroies = res;
            resolve(self.buildSuccessResult<musicCategroies>(data));
          } else
            resolve(self.buildFailedResult<musicCategroies>(res.message));
        });
      } catch (e) {
        logger.error(e);
        resolve(super.buildExceptionResult<musicCategroies>(e));
      }
    });
  }

  getMenu(condition: string, page: number): Promise<returnModel<musicSearchMenu>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        let info = new apiInfo("https://api.bilibili.com/audio/music-service-c/s", `&keyword=${encodeURIComponent(condition)}&page=${page}&pagesize=20&search_type=menus`, null, false);
        this.client.getResult(info).then((res) => {
          if (res.code == 0) {
            var data: musicSearchMenu = res;
            resolve(self.buildSuccessResult<musicSearchMenu>(data));
          } else
            resolve(self.buildFailedResult<musicSearchMenu>(res.message));
        });
      } catch (e) {
        logger.error(e);
        resolve(super.buildExceptionResult<musicSearchMenu>(e));
      }
    });
  }

  getSingers(condition: string, page: number): Promise<returnModel<musicSearchUser>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        let info = new apiInfo("https://api.bilibili.com/audio/music-service-c/s", `&keyword=${encodeURIComponent(condition)}&page=${page}&pagesize=20&search_type=musician`, null, false);
        this.client.getResult(info).then((res) => {
          if (res.code == 0) {
            var data: musicSearchUser = res;
            resolve(self.buildSuccessResult<musicSearchUser>(data));
          } else
            resolve(self.buildFailedResult<musicSearchUser>(res.message));
        });
      } catch (e) {
        logger.error(e);
        resolve(super.buildExceptionResult<musicSearchUser>(e));
      }
    });
  }

  getMusics(condition: string, type: string, page: number): Promise<returnModel<any>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        let info = new apiInfo("https://api.bilibili.com/audio/music-service-c/s", `&keyword=${encodeURIComponent(condition)}&page=${page}&pagesize=20&search_type=${type}`, null, false);
        this.client.getResult(info).then((res) => {
          if (res.code == 0)
            resolve(self.buildSuccessResult<any>(res));
          else
            resolve(self.buildFailedResult<any>(res.message));
        });
      } catch (e) {
        logger.error(e);
        resolve(super.buildExceptionResult<any>(e));
      }
    });
  }

  loadMusic(id: number): Promise<returnModel<songInfo>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        let info = new apiInfo("https://api.bilibili.com/audio/music-service-c/songs/playing", `&song_id=${id}`, null, true);
        this.client.getResult(info).then((res) => {
          if (res.code == 0) {
            let data: songInfo = res;
            resolve(self.buildSuccessResult<songInfo>(data));
          } else
            resolve(self.buildFailedResult<songInfo>(res.message));
        });
      } catch (e) {
        logger.error(e);
        resolve(super.buildExceptionResult<songInfo>(e));
      }
    });
  }

  followOperate(fid: number, follow: boolean): Promise<returnModel<any>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        let info = new apiInfo("http://api.bilibili.com/x/relation/modify", '', null, true);
        info.buildVer = apiProvider.Build4;
        let data = new dataInfo(`&act=${(follow ? 1 : 2)}&fid=${fid}&re_src=90`, apiProvider.Build4);
        this.client.postResult(info, data).then((res) => {
          if (res.code == 0)
            resolve(self.buildSuccessResult<any>());
          else
            resolve(self.buildFailedResult<any>(res.message));
        });
      } catch (e) {
        logger.error(e);
        resolve(super.buildExceptionResult<any>(e));
      }
    });
  }

  createCollectFolder(title: string, isOpen: number): Promise<returnModel<any>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        let info = new apiInfo("https://api.bilibili.com/audio/music-service-c/collections", '', null, true);
        let data = new dataInfo(`is_open=${isOpen}&mid=${current.instance.mid}&title=${title}`, apiProvider.Build4);
        this.client.postResult(info, data).then((res) => {
          if (res.code == 0)
            resolve(self.buildSuccessResult<any>());
          else
            resolve(self.buildFailedResult<any>(res.message));
        });
      } catch (e) {
        logger.error(e);
        resolve(super.buildExceptionResult<any>(e));
      }
    });
  }

  delCollectFolder(collectionId: number): Promise<returnModel<any>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        let info = new apiInfo(`https://api.bilibili.com/audio/music-service-c/collections/${collectionId}/del`, '', null, true);
        let data = new dataInfo(`collection=${collectionId}&mid=${current.instance.mid}`);
        this.client.postResult(info, data).then((res) => {
          if (res.code == 0)
            resolve(self.buildSuccessResult<any>());
          else
            resolve(self.buildFailedResult<any>(res.message));
        });
      } catch (e) {
        logger.error(e);
        resolve(super.buildExceptionResult<any>(e));
      }
    });
  }

  addMusicCollect(collectionId: number, songId: string): Promise<returnModel<any>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        let info = new apiInfo(`https://api.bilibili.com/audio/music-service-c/collections/songs/${songId}`, '', null, true);
        let data = new dataInfo(`collection_id_list=${collectionId}&mid=${current.instance.mid}&song_id=${songId}`);
        this.client.postResult(info, data).then((res) => {
          if (res.code == 0)
            resolve(self.buildSuccessResult<any>());
          else
            resolve(self.buildFailedResult<any>(res.message));
        });
      } catch (e) {
        logger.error(e);
        resolve(super.buildExceptionResult<any>(e));
      }
    });
  }

  getSongCollections(): Promise<returnModel<songCollections>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        let info = new apiInfo("https://api.bilibili.com/audio/music-service-c/collections", `&mid=${current.instance.mid}&page_index=1&page_size=1000&sort=1`, null, true);
        this.client.getResult(info).then((res) => {
          if (res.code == 0)
            resolve(self.buildSuccessResult<songCollections>());
          else
            resolve(self.buildFailedResult<songCollections>(res.message));
        });
      } catch (e) {
        logger.error(e);
        resolve(super.buildExceptionResult<songCollections>(e));
      }
    });
  }

  getSongs(collectionId: number): Promise<returnModel<songInfo>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        let info = new apiInfo(`https://api.bilibili.com/audio/music-service-c/collections/${collectionId}/songs`, `&collection_id=${collectionId}&mid=${current.instance.mid}&page_index=1&page_size=500&sort=1`, null, true);
        this.client.getResult(info).then((res) => {
          if (res.code == 0) {
            let data: songInfo = res;
            resolve(self.buildSuccessResult<songInfo>(data));
          } else
            resolve(self.buildFailedResult<songInfo>(res.message));
        });
      } catch (e) {
        logger.error(e);
        resolve(super.buildExceptionResult<songInfo>(e));
      }
    });
  }

  getFollows(): Promise<returnModel<followMusician>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        let info = new apiInfo("https://api.bilibili.com/audio/music-service-c/users/upmembers", `&mid=${current.instance.mid}&page_index=1&page_size=1000`, null, true);
        this.client.getResult(info).then((res) => {
          if (res.code == 0) {
            let data: followMusician = res;
            resolve(self.buildSuccessResult<followMusician>(data));
          } else
            resolve(self.buildFailedResult<followMusician>(res.message));
        });
      } catch (e) {
        logger.error(e);
        resolve(super.buildExceptionResult<followMusician>(e));
      }
    });
  }

  getMenus(type: number): Promise<returnModel<Array<musicHomeMenu>>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        let info = new apiInfo("https://api.bilibili.com/audio/music-service-c/users/{0}/menus", `&page_index=1&page_size=1000&type=${type}`, null, true);
        this.client.getResult(info).then((res) => {
          if (res.code == 0) {
            let data: Array<musicHomeMenu> = res.data.list;
            resolve(self.buildSuccessResult<Array<musicHomeMenu>>(data));
          } else
            resolve(self.buildFailedResult<Array<musicHomeMenu>>(res.message));
        });
      } catch (e) {
        logger.error(e);
        resolve(super.buildExceptionResult<Array<musicHomeMenu>>(e));
      }
    });
  }

  getUpInfo(mid: number): Promise<returnModel<musicianInfo>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        let info = new apiInfo("https://api.bilibili.com/audio/music-service-c/users/upinfo",
          `&mid=${current.instance.mid}&upmid=${mid}`, null, true);
        this.client.getResult(info).then((res) => {
          if (res.code == 0) {
            let data: musicianInfo = res;
            resolve(self.buildSuccessResult<musicianInfo>(data));
          } else
            resolve(self.buildFailedResult<musicianInfo>(res.message));
        });
      } catch (e) {
        logger.error(e);
        resolve(super.buildExceptionResult<musicianInfo>(e));
      }
    });
  }

  getUpSongs(mid: number): Promise<returnModel<Array<musicHomeSong>>> {
    var self = this;
    return new Promise((resolve) => {
      try {
        let info = new apiInfo("https://api.bilibili.com/audio/music-service-c/songs/getupsongslist",
          `&isAll=true&mid=${mid}&pageIndex=1&pageSize=20&sortBy=0&sortType=0`, null, true);
        this.client.getResult(info).then((res) => {
          if (res.code == 0) {
            let data: Array<musicHomeSong> = res.data.list;
            resolve(self.buildSuccessResult<Array<musicHomeSong>>(data));
          } else
            resolve(self.buildFailedResult<Array<musicHomeSong>>(res.message));
        });
      } catch (e) {
        logger.error(e);
        resolve(super.buildExceptionResult<Array<musicHomeSong>>(e));
      }
    });
  }
}
export default new musicClient();